iT邦幫忙

2021 iThome 鐵人賽

DAY 1
1
Modern Web

用30天更加認識 React.js 這個好朋友系列 第 1

Day1-鐵人賽大綱 & 為什麼要使用 Hook?

  • 分享至 

  • xImage
  •  

鐵人賽大綱

在這次鐵人賽的挑戰中,主要的目標是希望自己和讀者們可以更加認識 React.js 或者是複習一下以前學過的知識,所以安排了幾個單元來進行介紹,預期介紹的單元如下:

  1. React hooks(會帶到 React Context)
  2. React 表單驗證
  3. Redux & Redux toolkit
  4. React Router v5
  5. React 動畫
  6. 其他瑣碎 React 特性功能

註: 本系列挑戰文會全部以 functional component 去做介紹

為什麼要使用 Hook?

那在進入 React hooks 單元前,先來了解一下什麼是 hook?為什麼要使用 Hook?

在 React.js 的官網提到

Hook 是 React 16.8 中增加的新功能。它讓你不必寫 class 就能使用 state 以及其他 React 的功能。

1. 為了搭配 functional component 一起使用

React 從以前的 class component 轉向 function component 的設計其實就是往 FP 的方向去發展,但純粹的 function component 本身要渲染到網頁畫面上時無法去控制和記憶狀態,所以這個部分就透過 hooks 去做補足,換句話說就是讓 functional component 能夠擁有狀態,然後 functional component 和 React hooks 都以函式的形式撰寫,這樣的好處是開發者可以自由的定義函式的傳入參數和回傳值,在設計程式碼上更有彈性。

2. 提升狀態邏輯的重用性

在過去,使用 class component 時需要使用 HOC(Higher Order Component) 與 Render Props 去進行 Code Reuse,但多層的 HOC 會造成 wrapper hell,維護性不佳,並且多層的 HOC 也可能會有 Props 命名衝突的問題。

class component 很多的程式碼也都和生命週期函式做綁定,如果有重複性邏輯會不好抽取出來,學習 JavaScript 的 class 語法也是一個拉高 React 學習的成本。

但我們現在可以將和某個小功能相關的程式碼邏輯放在同一個 custom hook 裡面,讓不同的元件需要該小功能時,就可以使用該 hook,減少程式碼的重複性,也更方便維護該功能。

每次呼叫一個 Hook 時,都會有一個完全獨立且隔離的 state,所以你甚至可以在一個 component 使用同一個客製化 Hook 兩次

使用 hook 的限制

看起來 hook 確實很強大,但它也有些使用上的限制:

  1. 只在元件最上層使用 Hook,不能在 loop、條件判斷、nest function(在 function scope 中宣告的 function)調用hook。
  2. 名稱必須是以 use 開頭,包括自己建立的 custom hook 也是
  3. 只在 React function component 呼叫 Hook

為什麼 React hook 只能在 function component 裡的頂層調用,不可以在條件式或迴圈、巢狀函式裡等地方調用?

這邊可以和 Day29 Fiber 段落的內容一起觀看,我們如果在元件內部使用了多個 hooks,它們的相關狀態、資料等會形成一個 linked list,每次渲染時就會依序照著這個 linked list 去執行 hook。

https://ithelp.ithome.com.tw/upload/images/20230610/20116883HveffBsFkm.png

這樣設計的好處是 hooks 在多個元件複用時,可以不用擔心會有重複命名的問題,而是透過像是索引的方式去區別各個的 hooks,因此如果在條件式、迴圈內部或是巢狀函式等地方使用到 hooks,每次渲染就有可能不會執行到某些 hooks 進而導致順序錯亂。

React hooks: not magic, just arrays 這篇文章的 And the naive implementation 段落,有模擬一個簡化版本的 useState,作者提到這不是用來表達 hook 底層的運作方式,但簡化版本的 useState 可以更容易讓你了解為什麼 React hook 只能在 function component 裡的頂層調用的原因。

在範例程式碼中,使用了 state 和 setters 兩個陣列還有 cursor 計數的變數,而每使用一個 useState hook,就會將 state 和 setters 兩個陣列推入新的元素,然後 cursor 加一。所以 state 會分別存 firstName 和 lastName 值,setters 存 setFirstName 和 setLastName,此時每次渲染元件時,useState 的回傳值就是透過 cursor 當作索引去分別取出 state 和 setters 兩個陣列的元素,索引值不對就會更新到不正確的 state,這樣就很容易理解為什麼 hooks 會有這個限制的原因了。

const [firstName, setFirstName] = useState("Rudi"); // cursor: 0
const [lastName, setLastName] = useState("Yardley"); // cursor: 1

在我們了解 hook 是什麼及為什麼要使用它後,接著就來認識一下有哪些 hook 吧!


下一篇
Day2-React Hook 篇-認識 useState
系列文
用30天更加認識 React.js 這個好朋友33
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言